﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WunderlistAPI;

namespace WunderList
{
	/// <summary>
	/// This is the panel for displaying tasks in Outlook
	/// </summary>
	public partial class WunderLookPanel : UserControl
	{
		/// <summary>
		/// Wunderlist connection
		/// </summary>
		private WunderlistConnection wlConnection;

		/// <summary>
		/// User's list of tasks
		/// </summary>
		private List<TaskList> lists;

		/// <summary>
		/// Initializes a new instance of the <see cref="WunderLookPanel"/> class.
		/// </summary>
		public WunderLookPanel()
		{
			InitializeComponent();

			// init tasks list
			lists = new List<TaskList>();

			// start in a disconnected state for now
			DisableControl();
		}

		/// <summary>
		/// Displays a dialog with a prompt and textbox where the user can enter information
		/// stolen from http://www.blackbeltcoder.com/Articles/winforms/dynamically-creating-a-winforms-dialog because the .net framework doesn't have an InputBox 
		/// for C# even though it's 2012 and at version 4.0 for god's sake...
		/// </summary>
		/// <param name="title">Dialog title</param>
		/// <param name="promptText">Dialog prompt</param>
		/// <param name="value">Sets the initial value and returns the result</param>
		/// <returns>Dialog result</returns>
		public static string Show(string title, string promptText, bool IsPassword)
		{
			Form form = new Form();
			Label label = new Label();
			TextBox textBox = new TextBox();
			Button buttonOk = new Button();

			form.Text = title;
			label.Text = promptText;
			textBox.UseSystemPasswordChar = IsPassword;

			buttonOk.Text = "OK";
			buttonOk.DialogResult = DialogResult.OK;

			label.SetBounds(9, 20, 372, 13);
			textBox.SetBounds(12, 36, 372, 20);
			buttonOk.SetBounds(228, 72, 75, 23);

			label.AutoSize = true;
			textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
			buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

			form.ClientSize = new Size(396, 107);
			form.Controls.AddRange(new Control[] { label, textBox, buttonOk });
			form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
			form.FormBorderStyle = FormBorderStyle.FixedDialog;
			form.StartPosition = FormStartPosition.CenterScreen;
			form.MinimizeBox = false;
			form.MaximizeBox = false;
			form.AcceptButton = buttonOk;

			form.ShowDialog();
			return textBox.Text;
		}


		/// <summary>
		/// Shows a dialog to collect and save user credentials
		/// </summary>
		private void GatherCredentials()
		{
			// login
			var email = Show("Wunderlist Login", "Email", false);
			if (string.IsNullOrEmpty(email)) return;

			// password
			var password = Show("Wunderlist Password", "Password", true);
			if (string.IsNullOrEmpty(password)) return;

			// save user credentials and connect
			Properties.Settings.Default.Email = email;
			Properties.Settings.Default.Password = password;
			Properties.Settings.Default.Save();
			Connect();
		}

		/// <summary>
		/// Connects and logs into the Wunderlist API
		/// </summary>
		void Connect()
		{
			// make sure user credentials are stored
			if (string.IsNullOrEmpty(Properties.Settings.Default.Email) || string.IsNullOrEmpty(Properties.Settings.Default.Password))
			{
				GatherCredentials();
				return;
			}

			try
			{
				
				DisableControl();

				// connect
				wlConnection = new WunderlistConnection(Properties.Settings.Default.Email);
				wlConnection.Login(Properties.Settings.Default.Password);

				// retrieve and bind lists
				lists = wlConnection.GetAllLists();
				BindLists();
			}
			catch (Exception ex)
			{
				// clear credentials so we can try again
				Properties.Settings.Default.Email = "";
				Properties.Settings.Default.Password = "";
				Properties.Settings.Default.Save();

				// inform user of disconnect and disable control
				DisableControl();
			}
		}

		/// <summary>
		/// Disables the panel, prompts user to reconnect.
		/// </summary>
		void DisableControl()
		{
			Title.Text = "Disconnected";
			TasksTree.Nodes.Clear();
			TasksTree.Nodes.Add("Double-click above to connect.");
			TasksTree.CheckBoxes = false;
			TasksTree.Enabled = false;
		}

		/// <summary>
		/// Binds the user lists to the tree, adding all tasks.
		/// </summary>
		void BindLists()
		{
			// enable control and reset it
			Title.Text = "Connected";
			TasksTree.Enabled = true;
			TasksTree.Nodes.Clear();
			TasksTree.CheckBoxes = true;

			// bind user lists
			foreach (var list in lists)
			{
				// add list to tree
				var listNode = new TreeNode(list.Name);
				listNode.Tag = list;
				TasksTree.Nodes.Add(listNode);

				// add tasks
				AppendTasks(list, listNode);
			}
		}

		/// <summary>
		/// Appends the lists tasks to the treeview.
		/// </summary>
		/// <param name="list">The list.</param>
		/// <param name="listNode">The list node.</param>
		void AppendTasks(TaskList list, TreeNode listNode)
		{
			// parse through each task
			for (int i = 0; i < list.Count; i++)
			{
				// create a node for each task
				var task = list[i];
				var taskNode = new TreeNode(task.Name);
				taskNode.Checked = task.Done;
				taskNode.Tag = task;
				listNode.Nodes.Add(taskNode);
			}
		}

		/// <summary>
		/// Handles the DoubleClick event of the Title control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void Title_DoubleClick(object sender, EventArgs e)
		{
			// reconnects to wunderlist
			Connect();
		}

		/// <summary>
		/// Handles the BeforeCheck event of the TasksTree control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Windows.Forms.TreeViewCancelEventArgs"/> instance containing the event data.</param>
		private void TasksTree_BeforeCheck(object sender, TreeViewCancelEventArgs e)
		{
			// get task item, ensure it's a task (not a list)
			var checkedTask = e.Node.Tag as Task;
			if (checkedTask == null)
			{
				e.Cancel = true;
				return;
			}

			try
			{
				// re-grab task (cached Tag apparently doesn't allow saving to the remote list)
				var task = wlConnection.GetTask(checkedTask.ID);

				// update and save task
				task.Done = !e.Node.Checked;
				task.Save();

				// resave task for future retrieval
				e.Node.Tag = task;
			}
			catch (Exception ex)
			{
				// reset task and attempt to reconnect
				e.Cancel = true;
				Connect();
			}
		}
	}
}
